class Render {
  // 初始化过的运行时缓存，单例
  static engine: any = {
    vue: null,
    react: null
  };

  static selectorSuffix = '-app';

  // 组件地址
  componentPath = '';

  // 需要传递的数据
  bindData = {};

  /**
   * 可适配的引擎渲染
   * @param componentPath 组件地址
   */
  constructor(componentPath: string, data?: object) {
    this.componentPath = componentPath;
    this.bindData = data || {};
    this.componentAdapter();
  }

  /**
   * 创建挂载点
   */
  createMountDom() {
    for (let engine in Render.engine) {
      let div = document.createElement('div');
      let selector = `${engine}${Render.selectorSuffix}`;
      div.setAttribute('id', selector);
      div.classList.add('app-root');
      if (!document.querySelector(`#${selector}`)) {
        document.body.appendChild(div);
      }
    }
    Array.from(document.querySelectorAll('.app-root')).forEach(
      (div: any) => (div.style.display = 'none')
    );
  }

  /**
   * 是 Vue 还是 React?
   */
  componentAdapter() {
    const ext = this.componentPath.split('.').pop();
    switch (ext) {
      case 'vue':
        this.vueMount();
        break;
      case 'jsx':
        this.reactMount();
      default:
        break;
    }
  }

  /**
   * Vue组件挂载
   */
  async vueMount() {
    if (!Render.engine.vue) {
      const m = await import('vue');
      Render.engine.vue = m.default;
    }
    let dom: any = document.querySelector(`#vue${Render.selectorSuffix}`);
    if (!dom) this.createMountDom();
    dom = document.querySelector(`#vue${Render.selectorSuffix}`);
    dom.removeAttribute('style');
    Render.dynamicVue(this.componentPath, dom);
  }

  /**
   * 动态载入vue组件静态方法
   * 这个方法只能在
   * @param path 
   * @param dom 
   * @param propsData 
   */
  static dynamicVue(path: string, dom, propsData={}) {
    import(`@components/${path}`).then(m => {
      const Component = Render.engine.vue.extend(m.default);
      new Component({
        propsData
      }).$mount(dom, true);
    });
  }

  /**
   * React组件挂载
   */
  async reactMount() {
    if (!Render.engine.react) {
      const m = await import('nervjs');
      Render.engine.react = m.default;
    }
    let dom: any = document.querySelector(`#react${Render.selectorSuffix}`);
    if (!dom) this.createMountDom();
    dom = document.querySelector(`#react${Render.selectorSuffix}`);
    dom.removeAttribute('style');
    import(`@components/${this.componentPath}`).then(m => {
      Render.engine.react.render(Render.engine.react.createElement(m.default), dom);
    });
  }
}

export default Render;
